package org.ioflow
{
	import com.worlize.websocket.WebSocket;
	import com.worlize.websocket.WebSocketErrorEvent;
	import com.worlize.websocket.WebSocketEvent;
	
	import flash.events.EventDispatcher;
	
	import org.ioflow.events.ConnectionFailEvent;
	import org.ioflow.events.ConnectionSuccessEvent;
	import org.ioflow.events.DisconnectEvent;
	import org.ioflow.events.MessageEvent;
	import org.ioflow.utils.UrlHelper;

	public class IOflow extends EventDispatcher
	{
		private var m_socket:WebSocket;
		private var m_isConnected:Boolean;
		private var m_isConnecting:Boolean;
		private var m_debug:Boolean;
		private var m_timeout:uint;
		private var m_origin:String;
		private var m_protocols:*;
		
		public function IOflow(origin:String = "*", protocols:* = "wamp", timout:uint = 10000, debug:Boolean = false)
		{
			m_socket = null;
			m_isConnected = false;
			m_isConnecting = false;
			m_debug = debug;
			m_timeout = timout;
			m_protocols = protocols;
			m_origin = origin;
		}
		
		public function connect(path:String):void
		{
			if (m_isConnected)
			{
				throw new Error("Already connected");
			}
			
			if (m_isConnecting)
			{
				throw new Error("Already connecting");
			}
			m_isConnecting = true;
			const url:UrlHelper = new UrlHelper(path);
			if (url.protocol != "ws" && url.protocol != "wss")
			{
				url.protocol = "ws";
			}
			
			
			url.path = url.path + (url.path.charAt(url.path.length - 1) == '/'?"__webSocket__/":"/__webSocket__/");
			
			m_socket = new WebSocket(url.toUrlString(), m_origin, m_protocols, m_timeout);
			m_socket.addEventListener(WebSocketEvent.CLOSED, handleWebSocketClosed);
			m_socket.addEventListener(WebSocketEvent.OPEN, handleWebSocketOpen);
			m_socket.addEventListener(WebSocketEvent.MESSAGE, handleWebSocketMessage);
			m_socket.addEventListener(WebSocketErrorEvent.CONNECTION_FAIL, handleConnectionFail);
			m_socket.connect();
		}
		
		public function send(message:Object):void
		{
			if (m_isConnected)
			{
				const msg:String = JSON.stringify({d:message});
				m_socket.sendUTF(msg);
			}
			else
			{
				throw new Error("This instance is not connected.");
			}
		}
		
		private function handleWebSocketClosed(event:WebSocketEvent):void
		{
			dispatchEvent(new DisconnectEvent(this));
		}
		
		private function handleWebSocketOpen(event:WebSocketEvent):void
		{
			m_isConnected = true;
			dispatchEvent(new ConnectionSuccessEvent(this));
		}
		
		private function handleWebSocketMessage(event:WebSocketEvent):void
		{
			const message:Object = JSON.parse(event.message.utf8Data);
			dispatchEvent(new MessageEvent(this, message));
		}
		
		private function handleConnectionFail(event:WebSocketErrorEvent):void
		{
			m_isConnected = false;
			dispatchEvent(new ConnectionFailEvent(this, event.text));
		}
	}
}